﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace AutoCodeGenerator.InterfaceAutoBuilder
{
    /* 需求： 在构建代码时，只需要定义类，就自动生成接口，接口内容为构建public方法的接口
     * 实现：
     * 首先确定标识，添加[AutoInterface]标识的类自动生成接口，找到所有public的方法，
     * 如果有方法不生成接口对外，则标记[AutoIgnore]
     */


    public class BaseClassInfo
    {
        /// <summary>
        /// 获得命名空间
        /// </summary>
        public NamespaceDeclarationSyntax NamespaceDeclaration { get; set; }
        /// <summary>
        ///  using指令信息
        /// </summary>
        public List<UsingDirectiveSyntax> UsingDirectives { get; set; } = new List<UsingDirectiveSyntax>();
        /// <summary>
        /// 
        /// </summary>
        public ClassDeclarationSyntax ClassDeclarations { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public InterfaceAttributeInfo InterfaceInfo { get; set; } = new InterfaceAttributeInfo();


        /// <summary>
        /// 接口特性信息
        /// </summary>
        public class InterfaceAttributeInfo
        {
            /// <summary>
            /// 接口名称
            /// </summary>
            public string InterfaceName { get; set; }
            /// <summary>
            /// 接口文件生成路劲
            /// </summary>
            public string InterfacePath { get; set; }
        }
    }



    /// <summary>
    /// 继承接口 代码生成器
    /// </summary>
    public class InterfaceSyntaxReceiver : ISyntaxReceiver
    {
        /// <summary>
        /// 忽略特性名称
        /// </summary>
        public string IgnoreAttributeName = "AutoIgnore";

        /// <summary>
        /// 生成接口特性名称
        /// </summary>
        public string InterfaceAttributeName = "AutoInterface";

        // 获得命名空间
        public NamespaceDeclarationSyntax NamespaceDeclaration { get; private set; }

        // 获得using指令
        public List<UsingDirectiveSyntax> UsingDirectives = new List<UsingDirectiveSyntax>();

        // 获得类名
        public List<BaseClassInfo> classDeclarations = new List<BaseClassInfo>();

        public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
        {
            //Debugger.Launch();
            // 获取所有 using 指令
            var usingDirectives = syntaxNode.DescendantNodes().OfType<UsingDirectiveSyntax>();
            if (usingDirectives.Any())
            {
                UsingDirectives.AddRange(usingDirectives);
            }

            if (syntaxNode is NamespaceDeclarationSyntax namespaceDeclaration)
            {
                NamespaceDeclaration = namespaceDeclaration;
            }
            var readEnd = false;
            if (syntaxNode is ClassDeclarationSyntax classDeclaration)
            {
                // 获取类声明的特性
                var attributes = classDeclaration.AttributeLists.SelectMany(attributeList =>
                    attributeList.Attributes.ToList());

                foreach (var attribute in attributes)
                {
                    var attributeName = attribute.Name is IdentifierNameSyntax identifierNameSyntax
                           ? identifierNameSyntax.Identifier.Text
                            : attribute.Name.ToString();

                    if (attributeName == InterfaceAttributeName)
                    {
                        var baseClassInfo = new BaseClassInfo
                        {
                            ClassDeclarations = classDeclaration,
                            NamespaceDeclaration = NamespaceDeclaration,
                            UsingDirectives = UsingDirectives
                        };
                        var attributeArgs = attribute.ArgumentList?.Arguments
                              .Select(arg => arg.Expression.ToString().Trim('\"'))
                              .ToList();
                        if (attributeArgs != null) 
                        {
                            if (attributeArgs.Count > 0)
                                baseClassInfo.InterfaceInfo.InterfaceName = attributeArgs.FirstOrDefault();

                            if (attributeArgs.Count > 1)
                                baseClassInfo.InterfaceInfo.InterfacePath = attributeArgs.LastOrDefault();
                        }
                        classDeclarations.Add(baseClassInfo);
                    }
                }
                readEnd = true;
            }
            if (readEnd)
            {
                UsingDirectives = new List<UsingDirectiveSyntax>();
                NamespaceDeclaration = null;
            }
        }


        /// <summary>
        /// 获取实体下的方法
        /// </summary>
        /// <param name="syntaxReceiver"></param>
        /// <param name="classDeclaration"></param>
        /// <returns></returns>
        public IEnumerable<MethodDeclarationSyntax> GetClassMethods(InterfaceSyntaxReceiver syntaxReceiver, ClassDeclarationSyntax classDeclaration)
        {
            // 获取类的方法
            var methods = classDeclaration.Members.OfType<MethodDeclarationSyntax>();
            // 获取类的所有公共方法
            IEnumerable<MethodDeclarationSyntax> publicMethods = methods.Where(method => method.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.PublicKeyword)));
            publicMethods = publicMethods.Where(method =>
            {
                if (!method.AttributeLists.Any())
                    return true;
                var attributeNames = method.AttributeLists.SelectMany(attributeList =>
                                           attributeList.Attributes.Select(attribute =>
                                               attribute.Name is IdentifierNameSyntax identifierNameSyntax
                                                   ? identifierNameSyntax.Identifier.Text
                                                   : attribute.Name.ToString()));
                return !attributeNames.Contains(syntaxReceiver.IgnoreAttributeName);
            }).Select(x => x).ToList();
            return publicMethods;
        }
    }
}
